/* 
 * File:   Dataset.h
 * Author: cjjonker
 *
 * Created on 20 december 2012, 15:29
 */

#ifndef DATASET_H
#define	DATASET_H

#include <string>
#include <iostream>
#include <cmath>

template<typename Data>
class Dataset {

    public:
        Dataset(){};
        Dataset(Data *dat, int dim);
        
        void setData(Data *dat, int dim);
        
        virtual Data getData(int x);
        virtual Data getData(float x, float y);
        
        virtual int dim();
        virtual void dim(int d);
    
    protected:
        int d_dim;
        Data *d_data;
};




template<typename Data>
Dataset<Data>::Dataset(Data* dat, int dim)
: d_data(dat), d_dim(dim)
{
}

template<typename Data>
void Dataset<Data>::setData(Data* dat, int dim)
{
    d_data = dat;
    d_dim = dim;
}

// Returns interpolated datapoint (or vector)
template<typename Data>
Data Dataset<Data>::getData(float x, float y)
{
    int idx1 = floor(y) * d_dim + floor(x);
    int idx2 = floor(y) * d_dim + floor(x + 1);
    int idx3 = floor(y + 1) * d_dim + floor(x);
    int idx4 = floor(y + 1) * d_dim + floor(x + 1);
    
    if (idx3 >= d_dim * d_dim)
        idx3 = idx1;
    
    if (idx4 >= d_dim * d_dim)
        idx4 = idx2;
    
    Data v1 = getData(idx1);
    Data v2 = getData(idx2);
    Data v3 = getData(idx3);
    Data v4 = getData(idx4);
    
    float dum;
    float r = 1 - std::modf(x, &dum);
    float s = 1 - std::modf(y, &dum);
    
    Data leftMean = v1 * s + v3 * (1 - s);    
    Data rightMean = v2 * s + v4 * (1 - s);
    
    return leftMean * r + rightMean * (1 - r);
}

// Returns datapoint at specific index
template<typename Data>
Data Dataset<Data>::getData(int idx)
{
    return d_data[idx];
}

template<typename Data>
inline void Dataset<Data>::dim(int d) { d_dim = d; }

template<typename Data>
inline int Dataset<Data>::dim() { return d_dim; }


#endif	/* DATASET_H */

